package com.tomato.zip.service;

import com.tomato.zip.enums.ZipType;
import com.tomato.zip.errors.ZipErrorType;
import com.tomato.zip.exception.ZipException;
import lombok.extern.slf4j.Slf4j;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.List;

/**
 * zip压缩包服务
 */
@Component
@Slf4j
public class ZipService implements BaseZip {

    @Override
    public ZipType getZipType() {
        return ZipType.ZIP;
    }


    /**
     * 创建压缩包
     *
     * @param zip      压缩包文件
     * @param password 压缩包密码
     * @param files    被压缩的文件
     */
    public void compress(File zip, String password, List<File> files) {
        try {
            if (zip == null) {
                throw new ZipException(ZipErrorType.COMPRESS_FILE_NULL);
            }
            // 校验要压缩的文件是否存在
            fileExists(files);

            ZipFile zipFile = createZipFile(zip, password);

            ZipParameters zipParameters = new ZipParameters();

            if (StringUtils.isNotBlank(password)) {
                zipParameters.setEncryptFiles(true);
                zipParameters.setEncryptionMethod(EncryptionMethod.ZIP_STANDARD);
            }

            for (File file : files) {
                if (file.isDirectory()) {
                    zipFile.addFolder(file);
                    continue;
                }
                zipFile.addFile(file, zipParameters);
            }

            log.info(">>>压缩文件成功<<<");
        } catch (net.lingala.zip4j.exception.ZipException e) {
            log.error("压缩文件失败: {}", e);
            throw new ZipException(e.getMessage());
        }
    }

    @Override
    public void extractAll(File zip, String password, String path) {
        try {
            ZipFile zipFile = createZipFile(zip, password);
            zipFile.extractAll(path);
        } catch (net.lingala.zip4j.exception.ZipException e) {
            log.error("解压文件失败: {}", e);
            throw new ZipException(e.getMessage());
        }
    }

    @Override
    public void extractFile(File zip, String fileName, String password, String path) {
        try {
            ZipFile zipFile = createZipFile(zip, password);
            zipFile.extractFile(fileName, path);
        } catch (net.lingala.zip4j.exception.ZipException e) {
            log.error("解压{}文件失败: {}", fileName, e);
            throw new ZipException(e.getMessage());
        }
    }

    @Override
    public void addFile(File zip, String password, File file) {
        try {
            ZipFile zipFile = createZipFile(zip, password);
            zipFile.addFile(file);
        } catch (net.lingala.zip4j.exception.ZipException e) {
            log.error("压缩文件失败:{}", e);
            throw new ZipException(e.getMessage());
        }
    }

    private ZipFile createZipFile(File zip, String password) {
        // 判断是否支持该类型
        if (!isLegal(zip)) {
            throw new ZipException(ZipErrorType.COMPRESS_FILE_NOT_SUPPORT);
        }
        return StringUtils.isBlank(password) ? new ZipFile(zip) : new ZipFile(zip, password.toCharArray());
    }


}
